/**
  ******************************************************************************
  * @file    ringbuf.c
  * @author  Milandr Application Team
  * @version V0.0.3
  * @date    26/08/2022
  * @brief   Ring buffer functions.
  ******************************************************************************
  * <br><br>
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, MILANDR SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2024 Milandr</center></h2>
  */

/* Includes ------------------------------------------------------------------*/
#include "ringbuf.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  RingBuf_Init - Ring buffer initialization
  * @param  ringbuf: pointer to a RingBuf_TypeDef
  * @param  ptr_buf: pointer to an array for ring buffer
  * @param  size: ring buffer size
  * @retval None
  */
void RingBuf_Init(RingBuf_TypeDef *ringbuf, uint32_t *ptr_buf, uint32_t size)
{
    ringbuf->buf = ptr_buf;
    ringbuf->size = size;
    ringbuf->wr = 0;
    ringbuf->rd = 0;
}

/**
  * @brief  RingBuf_WriteWord - Writing one word to a ring buffer
  * @param  ringbuf: pointer to a RingBuf_TypeDef
  * @param  data: the data to write
  * @retval None
  */
void RingBuf_WriteWord(RingBuf_TypeDef *ringbuf, uint32_t data)
{
    ringbuf->buf[ringbuf->wr++] = data;
    
    if(ringbuf->wr == ringbuf->size)
        ringbuf->wr = 0;
}

/**
  * @brief  RingBuf_Write - Writing data to a ring buffer
  * @param  ringbuf: pointer to a RingBuf_TypeDef
  * @param  data: pointer to array to write data
  * @param  size: size of data to be written in bytes
  * @retval None
  */
void RingBuf_Write(RingBuf_TypeDef *ringbuf, uint32_t *data, uint32_t size)
{
    uint32_t i, size_w;
    
    size_w = size / 4; // Number of written 32-bit words
    if(size % 4)       // If the number of bytes is not a multiple of 4, then increase the number of words by 1
        size_w++;
    
    for(i = 0; i < size_w; i++)
    {
        ringbuf->buf[ringbuf->wr++] = data[i];
    
        if(ringbuf->wr == ringbuf->size)
            ringbuf->wr = 0;
    }
}

/**
  * @brief  RingBuf_ReadWord - Reading one word from a ring buffer
  * @param  ringbuf: pointer to a RingBuf_TypeDef
  * @retval data: the data to read
  */
uint32_t RingBuf_ReadWord(RingBuf_TypeDef *ringbuf)
{
    uint32_t data = ringbuf->buf[ringbuf->rd++];
                 
    if(ringbuf->rd == ringbuf->size)
        ringbuf->rd = 0;
     
    return data;
}

/**
  * @brief  RingBuf_Read - Reading data from a ring buffer
  * @param  ringbuf: pointer to a RingBuf_TypeDef
  * @param  data: pointer to array to read data
  * @param  size: size of data to read in bytes
  * @retval None
  */
void RingBuf_Read(RingBuf_TypeDef *ringbuf, uint32_t *data, uint32_t size)
{
    uint32_t i, size_w;
    
    size_w = size / 4; // Number of written 32-bit words
    if(size % 4)       // If the number of bytes is not a multiple of 4, then increase the number of words by 1
        size_w++;
    
    for(i = 0; i < size_w; i++)
    {
        data[i] = ringbuf->buf[ringbuf->rd++];
                 
        if(ringbuf->rd == ringbuf->size)
            ringbuf->rd = 0;
    }
}

